import CryptoJS from 'crypto-js'

export interface SparkVoiceConfig {
  appId: string
  apiKey: string
  apiSecret: string
}

export interface VoiceRecognitionResult {
  text: string
  isFinal: boolean
}

export interface VoiceRecognitionStats {
  totalAttempts: number
  successCount: number
  errorCount: number
  averageResponseTime: number
  accuracy: number
}

export interface VoiceRecognitionConfig extends SparkVoiceConfig {
  maxRetries?: number
  retryDelay?: number
  enableCache?: boolean
  cacheTimeout?: number
}

interface CachedResult {
  text: string
  timestamp: number
  confidence: number
}

export class SparkVoiceRecognition {
  private config: VoiceRecognitionConfig
  private ws: WebSocket | null = null
  private mediaRecorder: MediaRecorder | null = null
  private audioContext: AudioContext | null = null
  private source: MediaStreamAudioSourceNode | null = null
  private processor: ScriptProcessorNode | null = null
  private stream: MediaStream | null = null
  private isRecording = false
  private silenceCount = 0
  private readonly silenceThreshold = 0.005
  private readonly maxSilenceFrames = 3
  
  // 性能监控
  private stats: VoiceRecognitionStats = {
    totalAttempts: 0,
    successCount: 0,
    errorCount: 0,
    averageResponseTime: 0,
    accuracy: 0
  }
  private startTime = 0
  private responseTimes: number[] = []
  
  // 错误处理和重连
  private retryCount = 0
  private maxRetries = 3
  private retryDelay = 1000
  private connectionTimeout: number | null = null
  
  // 缓存机制
  private enableCache = true
  private cacheTimeout = 300000 // 5分钟
  private resultCache = new Map<string, CachedResult>()
  
  // 音频数据回调
  private onAudioData?: (audioData: Float32Array) => void
  
  public onResult: ((result: VoiceRecognitionResult) => void) | null = null
  public onError: ((error: string) => void) | null = null

  constructor(config: VoiceRecognitionConfig, onAudioData?: (audioData: Float32Array) => void) {
    this.onAudioData = onAudioData
    // 验证配置参数
    if (!config.appId || !config.apiKey || !config.apiSecret) {
      throw new Error('星火语音识别配置不完整：appId、apiKey、apiSecret都不能为空')
    }
    
    console.log('SparkVoiceRecognition 初始化配置:')
    console.log('- APP_ID:', config.appId)
    console.log('- API_KEY:', config.apiKey ? '已设置' : '未设置')
    console.log('- API_SECRET:', config.apiSecret ? '已设置' : '未设置')
    
    // 设置配置参数，包含默认值
    this.config = {
      ...config,
      maxRetries: config.maxRetries ?? 3,
      retryDelay: config.retryDelay ?? 1000,
      enableCache: config.enableCache ?? true,
      cacheTimeout: config.cacheTimeout ?? 300000
    }
    
    // 初始化配置
    this.maxRetries = this.config.maxRetries!
    this.retryDelay = this.config.retryDelay!
    this.enableCache = this.config.enableCache!
    this.cacheTimeout = this.config.cacheTimeout!
  }
 
  static isSupported(): boolean {
    try {
      // 检查基本的Web API支持
      const hasNavigator = typeof navigator !== 'undefined'
      const hasMediaDevices = hasNavigator && navigator.mediaDevices
      const hasGetUserMedia = hasMediaDevices && typeof navigator.mediaDevices.getUserMedia === 'function'
      
      // 检查AudioContext支持（兼容不同浏览器）
      const AudioContextClass = window.AudioContext || (window as any).webkitAudioContext
      const hasAudioContext = typeof AudioContextClass === 'function'
      
      // 检查WebSocket支持
      const hasWebSocket = typeof WebSocket === 'function'
      
      console.log('浏览器支持检查:')
      console.log('- Navigator:', hasNavigator ? '✅' : '❌')
      console.log('- MediaDevices:', hasMediaDevices ? '✅' : '❌')
      console.log('- getUserMedia:', hasGetUserMedia ? '✅' : '❌')
      console.log('- AudioContext:', hasAudioContext ? '✅' : '❌')
      console.log('- WebSocket:', hasWebSocket ? '✅' : '❌')
      
      return hasNavigator && hasMediaDevices && hasGetUserMedia && hasAudioContext && hasWebSocket
    } catch (error) {
      console.error('检查浏览器支持时出错:', error)
      return false
    }
  }

  private getWebSocketUrl(): string {
    console.log('🔧 开始生成星火WebSocket URL...')
    console.log('配置信息:', {
      appId: this.config.appId ? '✅ 已设置' : '❌ 未设置',
      apiKey: this.config.apiKey ? '✅ 已设置' : '❌ 未设置',
      apiSecret: this.config.apiSecret ? '✅ 已设置' : '❌ 未设置'
    })
    
    if (!this.config.appId || !this.config.apiKey || !this.config.apiSecret) {
      throw new Error('星火语音识别配置不完整，请检查 appId、apiKey 和 apiSecret')
    }
    
    const host = 'iat-api.xfyun.cn'
    const path = '/v2/iat'
    const date = new Date().toUTCString()
    
    console.log('🕐 生成时间戳:', date)
    
    // 构建签名字符串 - 修复格式
    const signatureOrigin = `host: ${host}\ndate: ${date}\nGET ${path} HTTP/1.1`
    console.log('📝 签名原始字符串:', signatureOrigin)
    
    const signature = CryptoJS.HmacSHA256(signatureOrigin, this.config.apiSecret).toString(CryptoJS.enc.Base64)
    console.log('🔐 生成签名:', signature)
    
    // 构建authorization - 修复格式
    const authorization = `api_key="${this.config.apiKey}", algorithm="hmac-sha256", headers="host date request-line", signature="${signature}"`
    console.log('🔑 Authorization字符串:', authorization)
    
    // 修复编码方式 - 使用正确的UTF-8编码
    const authorizationBase64 = btoa(unescape(encodeURIComponent(authorization)))
    console.log('🔒 Base64编码后的Authorization:', authorizationBase64)
    
    // 构建WebSocket URL - 修复参数编码
    const params = new URLSearchParams({
      authorization: authorizationBase64,
      date: date,
      host: host
    })
    
    const url = `wss://${host}${path}?${params.toString()}`
    
    console.log('🌐 最终WebSocket URL:', url)
    return url
  }

 // 获取性能统计
  public getStats(): VoiceRecognitionStats {
    return { ...this.stats }
  }

  // 重置统计数据
  public resetStats(): void {
    this.stats = {
      totalAttempts: 0,
      successCount: 0,
      errorCount: 0,
      averageResponseTime: 0,
      accuracy: 0
    }
    this.responseTimes = []
  }

  // 更新统计数据
  private updateStats(isSuccess: boolean, responseTime?: number): void {
    this.stats.totalAttempts++
    
    if (isSuccess) {
      this.stats.successCount++
      if (responseTime) {
        this.responseTimes.push(responseTime)
        this.stats.averageResponseTime = this.responseTimes.reduce((a, b) => a + b, 0) / this.responseTimes.length
      }
    } else {
      this.stats.errorCount++
    }
    
    this.stats.accuracy = this.stats.totalAttempts > 0 
      ? (this.stats.successCount / this.stats.totalAttempts) * 100 
      : 0
  }

  private async connectWebSocket(): Promise<void> {
    return new Promise((resolve, reject) => {
      try {
        const url = this.getWebSocketUrl()
        console.log('🔗 正在连接WebSocket:', url)
        
        // 验证URL格式
        if (!url || !url.startsWith('wss://')) {
          const errorMsg = 'WebSocket URL格式错误，请检查API配置'
          console.error('❌', errorMsg)
          reject(new Error(errorMsg))
          return
        }
        
        this.ws = new WebSocket(url)
        
        // 设置连接超时 - 增加超时时间并添加更详细的错误处理
        this.connectionTimeout = window.setTimeout(() => {
          if (this.ws && this.ws.readyState === WebSocket.CONNECTING) {
            console.error('❌ WebSocket连接超时 (15秒)')
            this.ws.close()
            reject(new Error('WebSocket连接超时，请检查网络连接或稍后重试'))
          }
        }, 15000) // 增加到15秒超时
        
        this.ws.onopen = () => {
          if (this.connectionTimeout) {
            window.clearTimeout(this.connectionTimeout)
            this.connectionTimeout = null
          }
          
          console.log('✅ WebSocket连接成功')
          resolve()
        }
        
        this.ws.onmessage = (event) => {
          console.log('🔄 收到星火WebSocket消息:', event.data)
          
          try {
            // 检查消息数据是否为空或无效
            if (!event.data || typeof event.data !== 'string') {
              console.warn('⚠️ 收到无效的WebSocket消息数据')
              return
            }
            
            const data = JSON.parse(event.data)
            console.log('📥 解析后的星火数据:', data)
            
            // 验证响应数据结构
            if (!data || typeof data !== 'object') {
              console.error('❌ 无效的响应数据结构')
              this.onError?.('服务器返回无效数据格式')
              return
            }
            
            // 检查响应状态
            if (data.code !== 0) {
              console.error('❌ 星火API返回错误:', data)
              let errorMsg = data.message || `API错误 (code: ${data.code})`
              
              // 针对特定错误码提供更友好的错误信息
              switch (data.code) {
                case 10004:
                  errorMsg = '音频格式不支持，请检查麦克风设置'
                  break
                case 10013:
                  errorMsg = '参数错误，请检查API配置'
                  break
                case 11200:
                  errorMsg = '认证失败，请检查API密钥'
                  break
                case 11201:
                  errorMsg = 'API调用次数超限，请稍后重试'
                  break
                case 10160:
                  errorMsg = '音频数据过长，请缩短录音时间'
                  break
                case 10161:
                  errorMsg = '音频数据为空，请检查麦克风是否正常工作'
                  break
                default:
                  errorMsg = data.message || `API错误 (code: ${data.code})`
              }
              
              this.updateStats(false)
              this.onError?.(errorMsg)
              return
            }
            
            // 处理识别结果
            if (data.data && data.data.result) {
              const result = data.data.result
              console.log('🎯 识别结果数据:', result)
              
              if (result.ws && Array.isArray(result.ws)) {
                let recognizedText = ''
                
                // 拼接识别结果
                result.ws.forEach((ws: any) => {
                  if (ws.cw && Array.isArray(ws.cw)) {
                    ws.cw.forEach((cw: any) => {
                      if (cw.w && typeof cw.w === 'string') {
                        recognizedText += cw.w
                      }
                    })
                  }
                })
                
                console.log('📝 拼接后的识别文本:', recognizedText)
                
                if (recognizedText) {
                  // 判断是否为最终结果
                  const isFinal = data.data.status === 2
                  
                  // 缓存结果
                  if (this.enableCache && isFinal) {
                    const cacheKey = this.generateCacheKey(recognizedText)
                    this.resultCache.set(cacheKey, {
                      text: recognizedText,
                      timestamp: Date.now(),
                      confidence: 0.9 // 默认置信度
                    })
                  }
                  
                  this.onResult?.({
                    text: recognizedText,
                    isFinal: isFinal
                  })
                  
                  console.log(`🎤 语音识别${isFinal ? '完成' : '中间结果'}:`, recognizedText)
                  
                  // 更新统计数据
                  if (isFinal) {
                    const responseTime = Date.now() - this.startTime
                    this.updateStats(true, responseTime)
                  }
                }
              }
            }
            
            // 检查会话结束
            if (data.data && data.data.status === 2) {
              console.log('✅ 语音识别会话结束')
              this.cleanup()
            }
            
          } catch (error) {
            console.error('❌ 解析WebSocket消息失败:', error, '原始数据:', event.data)
            this.onError?.('解析服务器响应失败，请检查网络连接')
          }
        }
        
        this.ws.onerror = (error) => {
          if (this.connectionTimeout) {
            window.clearTimeout(this.connectionTimeout)
            this.connectionTimeout = null
          }
          
          console.error('❌ WebSocket连接错误:', error)
          this.updateStats(false)
          
          // 提供更详细的错误信息
          let errorMessage = 'WebSocket连接失败'
          if (error instanceof Event && error.target) {
            const ws = error.target as WebSocket
            if (ws.readyState === WebSocket.CLOSED) {
              errorMessage = 'WebSocket连接被服务器关闭，请检查网络连接'
            } else if (ws.readyState === WebSocket.CLOSING) {
              errorMessage = 'WebSocket连接正在关闭'
            }
          }
          
          // 自动重连机制
          if (this.retryCount < this.maxRetries) {
            this.retryCount++
            console.log(`🔄 WebSocket重连第 ${this.retryCount} 次...`)
            
            window.setTimeout(() => {
              this.connectWebSocket().then(resolve).catch(reject)
            }, this.retryDelay * this.retryCount)
            
            return
          }
          
          reject(new Error(errorMessage))
        }
        
        this.ws.onclose = (event) => {
          if (this.connectionTimeout) {
            window.clearTimeout(this.connectionTimeout)
            this.connectionTimeout = null
          }
          
          console.log('🔌 星火WebSocket连接关闭:', {
            code: event.code,
            reason: event.reason,
            wasClean: event.wasClean
          })
          
          // 提供更详细的关闭原因
          let closeReason = '连接已关闭'
          switch (event.code) {
            case 1000:
              closeReason = '正常关闭'
              break
            case 1001:
              closeReason = '端点离开'
              break
            case 1002:
              closeReason = '协议错误'
              break
            case 1003:
              closeReason = '不支持的数据类型'
              break
            case 1006:
              closeReason = '连接异常关闭'
              break
            case 1011:
              closeReason = '服务器错误'
              break
            case 1012:
              closeReason = '服务重启'
              break
            default:
              closeReason = event.reason || `未知错误 (code: ${event.code})`
          }
          
          if (!event.wasClean && this.isRecording) {
            console.warn(`⚠️ WebSocket异常关闭: ${closeReason}，尝试重连...`)
            this.updateStats(false)
            
            // 自动重连
            if (this.retryCount < this.maxRetries) {
              this.retryCount++
              console.log(`🔄 WebSocket重连第 ${this.retryCount} 次...`)
              
              window.setTimeout(() => {
                this.connectWebSocket().then(resolve).catch(reject)
              }, this.retryDelay * this.retryCount)
            } else {
              reject(new Error(`WebSocket连接失败: ${closeReason}`))
            }
          }
        }
        
      } catch (error) {
        console.error('❌ 创建WebSocket失败:', error)
        reject(error)
      }
    })
  }

  public async startRecognition(): Promise<void> {
    if (this.isRecording) {
      throw new Error('已在录音中')
    }

    this.stats.totalAttempts++
    this.startTime = Date.now()

    try {
      console.log('🎤 开始启动星火语音识别...')
      
      // 检查缓存
      if (this.enableCache) {
        this.cleanExpiredCache()
      }
      
      // 检查浏览器支持
      if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
        const errorMsg = '浏览器不支持麦克风访问，请使用Chrome、Firefox或Edge浏览器'
        console.error('❌', errorMsg)
        this.updateStats(false)
        if (this.onError) {
          this.onError(errorMsg)
        }
        return
      }
      
      console.log('请求麦克风权限...')
      
      // 获取麦克风权限和音频流
      try {
        const stream = await navigator.mediaDevices.getUserMedia({
          audio: {
            sampleRate: 16000,
            channelCount: 1,
            echoCancellation: true,
            noiseSuppression: true,
            autoGainControl: true
          }
        })
        
        console.log('✅ 麦克风权限获取成功')
        this.stream = stream
        
        // 创建WebSocket连接
        console.log('🔗 正在建立WebSocket连接...')
        await this.connectWebSocket()
        console.log('✅ WebSocket连接建立成功')
        
        // 开始音频录制
        console.log('🎵 开始音频录制...')
        this.startAudioRecording(stream)
        console.log('✅ 音频录制启动成功')
        
        // 标记为正在录音
        this.isRecording = true
        
        // 重置重试计数
        this.retryCount = 0
        
      } catch (micError) {
        console.error('❌ 获取麦克风权限失败:', micError)
        this.updateStats(false)
        
        if (this.onError) {
          let errorMessage = '获取麦克风权限失败'
          if (micError instanceof Error) {
            if (micError.name === 'NotAllowedError') {
              errorMessage = '用户拒绝了麦克风权限，请在浏览器设置中允许麦克风访问'
            } else if (micError.name === 'NotFoundError') {
              errorMessage = '未找到麦克风设备，请检查麦克风是否正确连接'
            } else if (micError.name === 'NotSupportedError') {
              errorMessage = '浏览器不支持麦克风访问功能'
            } else if (micError.name === 'OverconstrainedError') {
              errorMessage = '麦克风不支持所需的音频格式，请尝试其他麦克风'
            } else if (micError.name === 'SecurityError') {
              errorMessage = '安全限制阻止了麦克风访问，请检查浏览器安全设置'
            } else {
              errorMessage = `麦克风访问错误: ${micError.message}`
            }
          }
          this.onError(errorMessage)
        }
        
        // 自动重试机制
        if (this.retryCount < this.maxRetries) {
          this.retryCount++
          console.log(`🔄 正在进行第 ${this.retryCount} 次重试...`)
          
          window.setTimeout(() => {
            this.startRecognition().catch(retryError => {
              console.error('重试失败:', retryError)
            })
          }, this.retryDelay * this.retryCount) // 递增延迟
          
          return
        } else {
          console.error('❌ 已达到最大重试次数，停止重试')
        }
        
        throw micError
      }
      
    } catch (error) {
      console.error('❌ 启动星火语音识别失败:', error)
      this.updateStats(false)
      this.isRecording = false
      
      // 清理资源
      this.cleanup()
      
      // 自动重试机制
      if (this.retryCount < this.maxRetries) {
        this.retryCount++
        console.log(`🔄 正在进行第 ${this.retryCount} 次重试...`)
        
        window.setTimeout(() => {
          this.startRecognition().catch(retryError => {
            console.error('重试失败:', retryError)
          })
        }, this.retryDelay * this.retryCount) // 递增延迟
        
        return
      }
      
      if (this.onError) {
        let errorMessage = '启动星火语音识别失败'
        if (error instanceof Error) {
          if (error.message.includes('WebSocket')) {
            errorMessage = 'WebSocket连接失败，请检查网络连接'
          } else if (error.message.includes('超时')) {
            errorMessage = '连接超时，请检查网络状况后重试'
          } else if (error.message.includes('权限')) {
            errorMessage = '权限不足，请检查麦克风权限设置'
          } else {
            errorMessage = `启动失败: ${error.message}`
          }
        }
        this.onError(errorMessage)
      }
      
      throw error
    }
  }

  private startAudioRecording(stream: MediaStream): void {
    console.log('开始星火音频录制...')
    
    // 创建音频上下文 - 需要用户交互才能激活
    try {
      this.audioContext = new (window.AudioContext || (window as any).webkitAudioContext)({
        sampleRate: 16000
      })
      
      // 检查音频上下文状态
      if (this.audioContext.state === 'suspended') {
        console.log('音频上下文被挂起，尝试恢复...')
        this.audioContext.resume().then(() => {
          console.log('音频上下文已恢复')
          this.setupAudioProcessing(stream)
        }).catch(error => {
          console.error('恢复音频上下文失败:', error)
          if (this.onError) {
            this.onError('音频上下文激活失败，请确保在用户交互后启动语音识别')
          }
        })
      } else {
        this.setupAudioProcessing(stream)
      }
    } catch (error) {
      console.error('创建音频上下文失败:', error)
      if (this.onError) {
        this.onError('创建音频上下文失败')
      }
    }
  }

  private setupAudioProcessing(stream: MediaStream): void {
    if (!this.audioContext) {
      console.error('音频上下文未初始化')
      return
    }
    
    const source = this.audioContext.createMediaStreamSource(stream)
    
    // 创建增益节点 - 提高音频信号强度
    const gainNode = this.audioContext.createGain()
    gainNode.gain.value = 2.0 // 2倍增益
    
    // 创建高通滤波器 - 去除低频噪音
    const highPassFilter = this.audioContext.createBiquadFilter()
    highPassFilter.type = 'highpass'
    highPassFilter.frequency.value = 300 // 300Hz高通
    
    // 创建低通滤波器 - 去除高频噪音
    const lowPassFilter = this.audioContext.createBiquadFilter()
    lowPassFilter.type = 'lowpass'
    lowPassFilter.frequency.value = 3400 // 3400Hz低通，适合语音
    
    // 创建音频处理器 - 使用更小的缓冲区提高实时性（减少延迟）
    const processor = this.audioContext.createScriptProcessor(1024, 1, 1) // 从2048减少到1024，延迟减半
    
    // 静音检测状态
    let silenceFrameCount = 0
    const maxSilenceFrames = 3 // 连续3帧静音才跳过（约192ms）
    
    processor.onaudioprocess = (event) => {
      if (!this.isRecording || !this.ws || this.ws.readyState !== WebSocket.OPEN) {
        return
      }
      
      const inputBuffer = event.inputBuffer.getChannelData(0)
      
      // 传递音频数据给回调函数
      if (this.onAudioData) {
        this.onAudioData(inputBuffer)
      }
      
      // 检测静音 - 使用RMS计算音频能量，调整阈值
      const rms = Math.sqrt(inputBuffer.reduce((sum, sample) => sum + sample * sample, 0) / inputBuffer.length)
      const silenceThreshold = 0.005 // 降低静音阈值，提高敏感度
      
      if (rms > silenceThreshold) {
        // 检测到声音，重置静音计数器
        silenceFrameCount = 0
        
        try {
          const pcmData = this.convertToPCM16(inputBuffer)
          
          console.log('🎵 处理星火音频数据，长度:', pcmData.length, '字节, RMS:', rms.toFixed(4))
          
          // 发送音频数据帧 - 星火语音识别API格式
          const audioFrame = {
            data: {
              status: 1, // 1表示音频数据帧
              format: 'audio/L16;rate=16000',
              audio: btoa(String.fromCharCode(...Array.from(pcmData))),
              encoding: 'raw'
            }
          }
          
          if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(JSON.stringify(audioFrame))
          } else {
            console.warn('WebSocket连接不可用，跳过音频数据发送')
          }
        } catch (error) {
          console.error('处理音频数据时出错:', error)
        }
      } else {
        // 检测到静音，增加计数器
        silenceFrameCount++
        
        if (silenceFrameCount >= maxSilenceFrames) {
          console.log('🔇 连续静音检测，跳过发送 (RMS:', rms.toFixed(4), ')')
        } else {
          console.log('🔉 轻微静音，继续监听 (', silenceFrameCount, '/', maxSilenceFrames, ', RMS:', rms.toFixed(4), ')')
        }
      }
    }
    
    // 连接音频处理链
    source.connect(gainNode)
    gainNode.connect(highPassFilter)
    highPassFilter.connect(lowPassFilter)
    lowPassFilter.connect(processor)
    processor.connect(this.audioContext.destination)
    
    this.isRecording = true
    console.log('星火语音识别录音状态设置为true')
    
    // 发送开始帧 - 星火语音识别API标准格式
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      console.log('发送星火语音识别开始帧...')
      console.log('使用的app_id:', this.config.appId)
      
      const startFrame = {
        common: {
          app_id: this.config.appId
        },
        business: {
          language: 'zh_cn',
          domain: 'iat',
          accent: 'mandarin',
          vinfo: 1,
          vad_eos: 10000,
          ptt: 0,
          rlang: 'zh-cn',
          pd: 'iat',
          nunum: 1,
          speex_size: 60,
          nbest: 1,
          wbest: 1
        },
        data: {
          status: 0,
          format: 'audio/L16;rate=16000',
          audio: '',
          encoding: 'raw'
        }
      }
      
      console.log('📤 发送开始帧:', JSON.stringify(startFrame, null, 2))
      this.ws.send(JSON.stringify(startFrame))
      console.log('✅ 开始帧发送成功')
    } else {
      console.error('❌ WebSocket未就绪，无法发送开始帧')
      this.onError?.('WebSocket连接未就绪')
    }
  }

  private convertToPCM16(input: Float32Array): Uint8Array {
    try {
      const output = new ArrayBuffer(input.length * 2)
      const view = new DataView(output)
      
      for (let i = 0; i < input.length; i++) {
        // 确保输入值在有效范围内
        const sample = Math.max(-1, Math.min(1, input[i]))
        // 转换为16位PCM格式
        const pcmValue = Math.round(sample * 0x7FFF)
        view.setInt16(i * 2, pcmValue, true) // little-endian
      }
      
      return new Uint8Array(output)
    } catch (error) {
      console.error('PCM转换错误:', error)
      // 返回空数组作为fallback
      return new Uint8Array(0)
    }
  }

  stopRecognition(): void {
    console.log('🛑 停止星火语音识别...')
    
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      // 发送结束帧
      const endFrame = {
        data: {
          status: 2,
          format: 'audio/L16;rate=16000',
          audio: '',
          encoding: 'raw'
        }
      }
      
      console.log('📤 发送结束帧:', JSON.stringify(endFrame))
      this.ws.send(JSON.stringify(endFrame))
      console.log('✅ 结束帧发送成功')
    }
    
    this.isRecording = false
    this.cleanup()
  }

  public cleanup(): void {
    console.log('清理星火语音识别资源...')
    
    if (this.connectionTimeout) {
      window.clearTimeout(this.connectionTimeout)
      this.connectionTimeout = null
    }
    
    if (this.audioContext) {
      this.audioContext.close()
      this.audioContext = null
    }
    
    if (this.ws) {
      this.ws.close()
      this.ws = null
    }
    
    this.isRecording = false
    console.log('星火语音识别资源清理完成')
  }

  // 清理过期缓存
  private cleanExpiredCache(): void {
    const now = Date.now()
    for (const [key, result] of this.resultCache.entries()) {
      if (now - result.timestamp > this.cacheTimeout) {
        this.resultCache.delete(key)
      }
    }
  }

  // 生成缓存键
  private generateCacheKey(text: string): string {
    return CryptoJS.MD5(text).toString()
  }

  // 获取缓存结果
  private getCachedResult(key: string): CachedResult | null {
    const result = this.resultCache.get(key)
    if (result && Date.now() - result.timestamp < this.cacheTimeout) {
      return result
    }
    return null
  }
}

export default SparkVoiceRecognition